package JackSu.java01;

import org.junit.Test;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.Random;

public class InvocationHandlerProxyTest{

    //使用Proxy的newProxyInstance方法，三个参数classLoader类加载器，Class对象数组，实现了InvocationHandler接口的调用处理器。
    //可以代理指定接口的方法和Object中全部方法。代理类将生成一个以$Proxy开头的类名。并且代理类一定是public和final
    @Test
    public void invokeProxy(){//此处使用代理查看binarySearch方法的调用轨迹
        Object[] elements = new Object[1000];
        for(int i=0;i<elements.length;++i){
            Integer value=i+1;
            Object o = Proxy.newProxyInstance(null, new Class[]{Comparable.class}, new InvocationHandlerProxy(value));
            elements[i]=o;
        }
        //对于特定的类加载器和预设的一组接口来说，只能有一个代理类。也就是同一个类加载器和接口数组调用newProxyInstance只能得到同一个类的两个对象，getProxyClass可以获取该对象
        Class<?> clazz = Proxy.getProxyClass(null, Comparable.class);
        boolean isProxy = Proxy.isProxyClass(clazz);
        System.out.println(isProxy);
        Integer key = new Random().nextInt(elements.length) + 1;
        int result = Arrays.binarySearch(elements, key);//此处invoke方法代理了Comparable接口的compareTo方法，Integer对象调用compareTo
        if(result>=0)
            System.out.println(elements[result]);//此处invoke方法代理了Object接口的toString方法
    }

    class InvocationHandlerProxy implements InvocationHandler {
        private Object target;

        public InvocationHandlerProxy(Object target) {
            this.target = target;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.print(target+"."+method.getName()+"(");
            if(args!=null){
                for(int i=0;i<args.length;++i){
                    System.out.println(args[i]);
                    if(i<args.length-1)
                        System.out.print(",");
                }
            }
            System.out.println(")");
            return method.invoke(target,args);
        }
    }
}
